package com.fast.admin.common.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * @Title：实现cache共享
 * @author：YLC
 * @date：2018/7/31 10:58
 * @version：1.0
 **/
@Slf4j
public class ShiroCache<K, V> implements Cache<K, V> {
    private static final String REDIS_SHIRO_CACHE = "redis_shiro_cache";
    private String cacheKey;
    private long globExpire = 60;
    @Autowired
    private RedisTemplate redisTemplate;


    @SuppressWarnings({"rawtypes", "unchecked"})
    public ShiroCache(String name, RedisTemplate redisTemplate) {
        this.cacheKey = REDIS_SHIRO_CACHE + ":" + name + ":";
        this.redisTemplate = redisTemplate;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public ShiroCache(String name, RedisTemplate redisTemplate, long globExpire) {
        this.cacheKey = REDIS_SHIRO_CACHE + ":" + name + ":";
        this.redisTemplate = redisTemplate;
        this.globExpire = globExpire;
    }


    @Override
    public V get(K key) throws CacheException {
        return getSession(key);
    }

    @Override
    public V put(K key, V value) throws CacheException {
        setSession(key, value);
        return value;
    }

    @Override
    public V remove(K key) throws CacheException {
        V old = get(key);
        deleteSession(key);
        return old;
    }

    @Override
    public void clear() throws CacheException {
        deleteSession(keys());
    }

    @Override
    public int size() {
        return keys().size();
    }

    @Override
    public Set<K> keys() {
        return redisTemplate.keys(getCacheKey("*"));
    }

    @Override
    public Collection<V> values() {
        Set<K> set = keys();
        List<V> list = new ArrayList<V>();
        for (K s : set) {
            list.add(get(s));
        }
        return list;
    }

    private void setSession(K key, Object o) {
        redisTemplate.opsForValue().set(getCacheKey(key), o);
        //60分钟过期
        redisTemplate.expire(getCacheKey(key), globExpire, TimeUnit.MINUTES);
    }

    private V getSession(K key) {
        return (V) redisTemplate.opsForValue().get(getCacheKey(key));
    }

    private void deleteSession(Object key){
        redisTemplate.delete(getCacheKey(key));
    }

    @SuppressWarnings("unchecked")
    private K getCacheKey(Object k) {
        return (K) (this.cacheKey + k);
    }
}
